package leetcode.code1001;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import leetcode.IDebug;
import leetcode.helper.HelpDebug;

public class Solution implements IDebug {

	int n;

	public int[] gridIllumination(int n, int[][] lamps, int[][] queries) {
		this.n = n;
		Map<Long, Integer> rowLight = new HashMap<>();
		Map<Long, Integer> colLight = new HashMap<>();
		Map<Long, Integer> leftLight = new HashMap<>();
		Map<Long, Integer> rightLight = new HashMap<>();
		Set<Long> light = new HashSet<>();
		for (int[] lamp : lamps) {
			int x = lamp[0], y = lamp[1];
			long me = this.index(x, y);
			if (light.contains(me)) {// 筛选重复的灯
				continue;
			}
			light.add(me);
			int[] represents = this.represents(x, y);
			long index1 = this.index(represents[0], represents[1]);
			long index2 = this.index(represents[2], represents[3]);
			long index3 = this.index(represents[4], represents[5]);
			long index4 = this.index(represents[6], represents[7]);
			int row = rowLight.getOrDefault(index1, 0);
			rowLight.put(index1, row + 1);
			int col = colLight.getOrDefault(index2, 0);
			colLight.put(index2, col + 1);
			int left = leftLight.getOrDefault(index3, 0);
			leftLight.put(index3, left + 1);
			int right = rightLight.getOrDefault(index4, 0);
			rightLight.put(index4, right + 1);
		}
		int len = queries.length;
		int[] ans = new int[len];
		int pans = 0;
		for (int[] query : queries) {
			int x = query[0], y = query[1];
			int[] represents = this.represents(x, y);
			long index1 = this.index(represents[0], represents[1]);
			long index2 = this.index(represents[2], represents[3]);
			long index3 = this.index(represents[4], represents[5]);
			long index4 = this.index(represents[6], represents[7]);
			int the = 0;
			if (rowLight.containsKey(index1) || colLight.containsKey(index2) || leftLight.containsKey(index3)
					|| rightLight.containsKey(index4)) {
				the = 1;
			}
			ans[pans++] = the;
			this.closeRound(x, y, rowLight, colLight, leftLight, rightLight, light);
		}
		return ans;
	}

	private void closeRound(int x, int y, Map<Long, Integer> rowLight, Map<Long, Integer> colLight,
			Map<Long, Integer> leftLight, Map<Long, Integer> rightLight, Set<Long> light) {
		this.close(x, y, rowLight, colLight, leftLight, rightLight, light);// 忘了关自己
		this.close(x + 1, y, rowLight, colLight, leftLight, rightLight, light);
		this.close(x - 1, y, rowLight, colLight, leftLight, rightLight, light);
		this.close(x, y + 1, rowLight, colLight, leftLight, rightLight, light);
		this.close(x, y - 1, rowLight, colLight, leftLight, rightLight, light);
		this.close(x - 1, y - 1, rowLight, colLight, leftLight, rightLight, light);
		this.close(x + 1, y - 1, rowLight, colLight, leftLight, rightLight, light);
		this.close(x - 1, y + 1, rowLight, colLight, leftLight, rightLight, light);
		this.close(x + 1, y + 1, rowLight, colLight, leftLight, rightLight, light);
	}

	private void close(int x, int y, Map<Long, Integer> rowLight, Map<Long, Integer> colLight,
			Map<Long, Integer> leftLight, Map<Long, Integer> rightLight, Set<Long> light) {
		if (x < 0 || x == n || y < 0 || y == n) {// 越界就不做了
			return;
		}
		long me = this.index(x, y);
		if (!light.contains(me)) {// 有灯才要关
			return;
		}
		light.remove(me);
		int[] represents = this.represents(x, y);
		long index1 = this.index(represents[0], represents[1]);
		long index2 = this.index(represents[2], represents[3]);
		long index3 = this.index(represents[4], represents[5]);
		long index4 = this.index(represents[6], represents[7]);
		this.updateMap(index1, rowLight);
		this.updateMap(index2, colLight);
		this.updateMap(index3, leftLight);
		this.updateMap(index4, rightLight);
	}

	private void updateMap(long index, Map<Long, Integer> map) {
		int val = map.getOrDefault(index, 0);
		if (val > 1) {
			map.put(index, val - 1);
		} else if (val == 1) {
			map.remove(index);
		}
	}

	private long index(long x, long y) {
		return x * this.n + y;
	}

	private int[] represents(int x, int y) {
		int[] ans = new int[8];
		ans[0] = x;// 行代表(x,0)
		ans[1] = 0;
		ans[2] = 0;// 列代表(0,y)
		ans[3] = y;
		int leftx = 0;
		int lefty = 0;
		if (x == y) {
			leftx = 0;
			lefty = 0;
		} else if (x > y) {
			leftx = x - y;
			lefty = 0;
		} else {
			leftx = 0;
			lefty = y - x;
		}
		ans[4] = leftx;
		ans[5] = lefty;
		int rightx = 0;
		int righty = 0;
		int sub = this.n - 1 - y;
		if (x == sub) {
			rightx = 0;
			righty = this.n - 1;
		} else if (x > sub) {
			rightx = x - sub;
			righty = this.n - 1;
		} else {
			rightx = 0;
			righty = y + x;
		}
		ans[6] = rightx;
		ans[7] = righty;
		return ans;
	}

	@Override
	public void debug1() {
		int[] e = HelpDebug.str2array3("[1,0]");
		HelpDebug.compare(e, this.gridIllumination(5, HelpDebug.str2array1("[[0,0],[4,4]]"), HelpDebug.str2array1("[[1,1],[1,0]]")));
	}

	@Override
	public void debug2() {
		int[] e = HelpDebug.str2array3("[1,1]");
		HelpDebug.compare(e, this.gridIllumination(5, HelpDebug.str2array1("[[0,0],[4,4]]"), HelpDebug.str2array1("[[1,1],[1,1]]")));
	}

	@Override
	public void debug3() {
		int[] e = HelpDebug.str2array3("[1,1,0]");
		HelpDebug.compare(e, this.gridIllumination(5, HelpDebug.str2array1("[[0,0],[0,4]]"), HelpDebug.str2array1("[[0,4],[0,1],[1,4]]")));
	}

	@Override
	public void debug4() {
		int[] e = HelpDebug.str2array3("[1,0]");
		HelpDebug.compare(e, this.gridIllumination(2, HelpDebug.str2array1("[[0,1]]"), HelpDebug.str2array1("[[1,0],[1,1]]")));
	}

	public static void main(String[] args) {
//		2
//		[[0,1]]
//		[[1,0],[1,1]]
		Solution so = new Solution();
		so.debug4();
		so.debug1();
		so.debug2();
		so.debug3();
	}

}
